package com.jidu.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jidu.common.core.domain.AjaxResult;
import com.jidu.common.core.domain.BaseEntity;
import com.jidu.common.exception.ServiceException;
import com.jidu.common.utils.DateUtils;
import com.jidu.common.utils.SecurityUtils;
import com.jidu.common.utils.bean.BeanUtils;
import com.jidu.common.utils.uuid.IdUtils;
import com.jidu.domain.*;
import com.jidu.domain.dto.ApplyStudentDto;
import com.jidu.domain.vo.DataVo;
import com.jidu.mapper.*;
import com.jidu.service.ICourseStudentRelService;
import com.jidu.service.ISysStudentService;
import com.jidu.system.domain.SysUserRole;
import com.jidu.system.mapper.SysUserRoleMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.catalina.security.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.rmi.ServerException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学员Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-07-19
 */
@Service
public class SysStudentServiceImpl extends ServiceImpl<SysStudentMapper, SysStudent> implements ISysStudentService
{
    @Autowired
    private SysStudentMapper sysStudentMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private ICourseStudentRelService courseStudentRelService;
    @Autowired
    private CourseStudentRelMapper courseStudentRelMapper;
    @Autowired
    private SysCourseMapper sysCourseMapper;
    @Autowired
    private SysTeacherMapper sysTeacherMapper;
    @Autowired
    private SysClassMapper sysClassMapper;

    /**
     * 查询学员
     * 
     * @param id 学员主键
     * @return 学员
     */
    @Override
    public SysStudent selectSysStudentById(Long id)
    {
        return sysStudentMapper.selectSysStudentById(id);
    }

    /**
     * 查询学员列表
     * 
     * @param sysStudent 学员
     * @return 学员
     */
    @Override
    public List<SysStudent> selectSysStudentList(SysStudent sysStudent)
    {
        return sysStudentMapper.selectSysStudentList(sysStudent);
    }

    /**
     * 新增学员
     * 
     * @param sysStudent 学员
     * @return 结果
     */
    @Override
    public int insertSysStudent(SysStudent sysStudent)
    {
        sysStudent.setCreateTime(DateUtils.getNowDate());
        return sysStudentMapper.insertSysStudent(sysStudent);
    }

    /**
     * 修改学员
     * 
     * @param sysStudent 学员
     * @return 结果
     */
    @Override
    public int updateSysStudent(SysStudent sysStudent)
    {
        sysStudent.setUpdateTime(DateUtils.getNowDate());
        return sysStudentMapper.updateSysStudent(sysStudent);
    }

    /**
     * 批量删除学员
     * 
     * @param ids 需要删除的学员主键
     * @return 结果
     */
    @Override
    public int deleteSysStudentByIds(Long[] ids)
    {
        return sysStudentMapper.deleteSysStudentByIds(ids);
    }

    /**
     * 删除学员信息
     * 
     * @param id 学员主键
     * @return 结果
     */
    @Override
    public int deleteSysStudentById(Long id)
    {
        return sysStudentMapper.deleteSysStudentById(id);
    }

    @Transactional(readOnly = false,rollbackFor = Exception.class)
    @Override
    public Boolean apply(ApplyStudentDto dto) {
        //根据手机号查询一下该学生是否存在
        SysStudent one = this.lambdaQuery()
                .eq(SysStudent::getDelFlag, "0")
                .eq(SysStudent::getMobile, dto.getMobile())
                .one();
        if (one != null){
            //代表已经存在了该用户，拿课程id以及用户id查询一下课程学生关系表是否存在这个课程
            CourseStudentRel courseStudentRel = courseStudentRelMapper.selectByCourseStudent(dto.getCourseId(), one.getId());
            if (courseStudentRel == null){
                //学生课程关系表
                CourseStudentRel r = new CourseStudentRel();
                r.setStudentId(one.getId());
                r.setCourseId(dto.getCourseId());
                r.setTeacherId(dto.getTeacherId());
                r.setClassId(dto.getClassId());
                r.setNum(dto.getNumber());
                r.setResNum(dto.getNumber());
                r.setPrice(dto.getPrice());
                r.setStatus("0");
                r.setDelFlag("0");
                r.setOrgId(1L);
                r.setRemark(dto.getRemark());
                r.setCreateTime(new Date());
                r.setUpdateTime(new Date());
                r.setCreateBy(SecurityUtils.getLoginUser().getUserId().toString());
                courseStudentRelMapper.insertCourseStudentRel(r);
                return true;
            }
            throw new RuntimeException("该课程还在进行中,请勿重复选择该课程!");
        }
        SysStudent sysStudent = new SysStudent();
        //设置一个初始密码
        dto.setPassword(SecurityUtils.encryptPassword(dto.getMobile()));
        BeanUtils.copyProperties(dto,sysStudent);
        sysStudent.setOrgId(1L);
        sysStudent.setCreateTime(new Date());
        sysStudent.setUpdateTime(new Date());
        sysStudent.setCreateBy(SecurityUtils.getLoginUser().getUserId().toString());
        boolean i = this.save(sysStudent);

        //添加角色
        if (i){
            SysUserRole role = new SysUserRole();
            role.setRoleId(3L);
            role.setUserId(sysStudent.getId());
            List<SysUserRole> roleUserList = new ArrayList<>();
            roleUserList.add(role);
            if (!CollectionUtils.isEmpty(roleUserList)){
                sysUserRoleMapper.batchUserRole(roleUserList);
            }
        }

        //学生课程关系表
        CourseStudentRel r = new CourseStudentRel();
        r.setStudentId(sysStudent.getId());
        r.setCourseId(dto.getCourseId());
        r.setTeacherId(dto.getTeacherId());
        r.setClassId(dto.getClassId());
        r.setNum(dto.getNumber());
        r.setResNum(0);
        r.setPrice(dto.getPrice());
        r.setStatus("0");
        r.setOrgId(1L);
        r.setDelFlag("0");
        r.setIsChangeClass("0");
        r.setRemark(dto.getRemark());
        r.setCreateTime(new Date());
        r.setUpdateTime(new Date());
        r.setCreateBy(SecurityUtils.getLoginUser().getUserId().toString());
        courseStudentRelMapper.insertCourseStudentRel(r);



        //进学生课程关系表 一个学生是可以选多门课程的  然后每门课的老师也是可选的嘛还是？？  以及班级是系统安排的还是 怎么说
        //学生班级关系表
        //选择老师还是选择课程（老师自动带出）
        //还需要选择课时嘛

        return true;

        //看看需不需要进
    }

    @Override
    public List<Map<String, Object>> studentList(ApplyStudentDto dto) {
        return courseStudentRelMapper.studentList(dto);
    }

    @Override
    public ApplyStudentDto getStudentCourse(Long studentId, Long courseStudentId) {
        SysStudent one = this.lambdaQuery().eq(SysStudent::getDelFlag, "0")
                .eq(SysStudent::getId, studentId).one();
        if (one == null){
            throw new RuntimeException("学生不存在");
        }
        ApplyStudentDto dto = new ApplyStudentDto();
        BeanUtils.copyProperties(one,dto);
        dto.setStudentId(one.getId());
        CourseStudentRel courseStudentRel = courseStudentRelMapper.selectCourseStudentRelById(courseStudentId);
        if (courseStudentRel != null){
            dto.setResNum(courseStudentRel.getResNum());
            dto.setStatus(courseStudentRel.getStatus());
            dto.setRemark(courseStudentRel.getRemark());
            dto.setLeaveTimes(courseStudentRel.getLeaveTimes());
            dto.setCourseId(courseStudentRel.getCourseId());
            dto.setClassId(courseStudentRel.getClassId());
            dto.setTeacherId(courseStudentRel.getTeacherId());
            dto.setNumber(courseStudentRel.getNum());
            dto.setCreateTime(courseStudentRel.getCreateTime());
            dto.setPrice(courseStudentRel.getPrice());
            dto.setRemark(courseStudentRel.getRemark());
            dto.setCourseStudentId(courseStudentRel.getId());
            dto.setIsChangeClass(courseStudentRel.getIsChangeClass());
            SysCourse sysCourse = sysCourseMapper.selectSysCourseById(courseStudentRel.getCourseId());
            if (sysCourse != null){
                dto.setCourseName(sysCourse.getName());
            }
            SysClass sysClass = sysClassMapper.selectSysClassById(courseStudentRel.getClassId());
            if (sysClass != null){
                dto.setClassName(sysClass.getName());
            }
            SysTeacher sysTeacher = sysTeacherMapper.selectSysTeacherById(courseStudentRel.getTeacherId());
            if (sysTeacher != null){
                dto.setTeacherName(sysTeacher.getName());
            }
        }
        return dto;
    }

    @Transactional
    @Override
    public Boolean exit(ApplyStudentDto applyStudentDto) {
        boolean flag = false;
        if (applyStudentDto.getStudentId() != null){
            //修改学生表
            SysStudent student = new SysStudent();
            student.setId(applyStudentDto.getStudentId());
            student.setName(applyStudentDto.getName());
            student.setParentName(applyStudentDto.getParentName());
            student.setMobile(applyStudentDto.getMobile());
            student.setBirthday(applyStudentDto.getBirthday());
            this.updateSysStudent(student);
            flag = true;
        }
        if (applyStudentDto.getCourseStudentId() != null){
            //修改课程学生表
            CourseStudentRel rel = new CourseStudentRel();
            rel.setId(applyStudentDto.getCourseStudentId());
            rel.setClassId(applyStudentDto.getClassId());
            rel.setCourseId(applyStudentDto.getCourseId());
            rel.setTeacherId(applyStudentDto.getTeacherId());
            rel.setNum(applyStudentDto.getNumber());
            rel.setDelFlag(applyStudentDto.getDelFlag());
            CourseStudentRel one = courseStudentRelService.lambdaQuery().eq(CourseStudentRel::getId, applyStudentDto.getCourseStudentId()).one();
            if (one != null){
                if (!one.getNum().equals(rel.getNum())){
                    rel.setResNum((applyStudentDto.getNumber()-one.getNum())+one.getResNum());
                }
            }

            rel.setPrice(applyStudentDto.getPrice());
            rel.setRemark(applyStudentDto.getRemark());
            courseStudentRelMapper.updateCourseStudentRel(rel);
            flag = true;
        }
        return flag;
    }

    @Override
    public Boolean updatePassword(String oldPassword,String newPassword,String twoNewPassword, Long studentId) {
        //根据用户id查询一下
        SysStudent one = this.lambdaQuery().eq(SysStudent::getDelFlag, "0")
                .eq(SysStudent::getId, studentId).one();
        if (one == null){
            throw new ServiceException("用户不存在!");
        }
        if (!SecurityUtils.matchesPassword(oldPassword,one.getPassword())){
            throw new ServiceException("原密码输入错误!");
        }
        if (!newPassword.equals(twoNewPassword)){
            throw new ServiceException("两次输入新密码不一致!");
        }
        //新密码不能和原密码相同
        if (SecurityUtils.matchesPassword(newPassword,one.getPassword())){
            throw new ServiceException("新密码不能和原密码相同!");
        }
        one.setPassword(SecurityUtils.encryptPassword(newPassword));
        return this.updateById(one);
    }

    @Override
    public Map<String, Object> login(Map<String, String> paramsMap) {
        String mobile = paramsMap.get("mobile");
        String password = paramsMap.get("password");
        SysStudent one = this.lambdaQuery().eq(SysStudent::getDelFlag, "0")
                .eq(SysStudent::getMobile, mobile)
//                .eq(SysStudent::getPassword, SecurityUtils.encryptPassword(password))
                .one();
        if (one == null){
            throw new ServiceException("该用户不存在!");
        }
        if (!SecurityUtils.matchesPassword(password,one.getPassword())){
            throw new ServiceException("密码错误!");
        }
        List<CourseStudentRel> list = courseStudentRelService.lambdaQuery().eq(CourseStudentRel::getStudentId, one.getId()).eq(CourseStudentRel::getDelFlag, "0")
                .in(CourseStudentRel::getIsChangeClass, new String[]{"0", "2"}).list();
        if (!CollectionUtils.isEmpty(list)){
            one.setCourseStudentRels(list);
        }
        List<Map<String, String>> maps = sysUserRoleMapper.selectByRoles(one.getId());
        if (!CollectionUtils.isEmpty(maps)){
            one.setRoles(maps);
        }
        Map<String, Object> claims = new HashMap<>();
        claims.put("login_app_key", IdUtils.fastUUID());
        String token = Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, "abcdefghijklmnopqrstuvwxyz").compact();
        Map<String,Object> map = new HashMap();
        one.setPassword(null);
        map.put("userInfo", one);
        map.put("token", token);
        return map;
    }

    @Override
    public DataVo dataBoard() {
        String date = DateUtils.getDate();
        String startTime = date + " 00:00:00";
        String endTime = date + " 23:59:59";
        DataVo vo = new DataVo();
        Long count = this.lambdaQuery().eq(SysStudent::getDelFlag, "0").ge(BaseEntity::getCreateTime,startTime).le(BaseEntity::getCreateTime,endTime).count();
        vo.setTodayUserNumber(count != null && count>0?count.intValue():0);
        Long count1 = this.lambdaQuery().eq(SysStudent::getDelFlag, "0").count();
        vo.setTotalUserNumber(count1 != null && count1>0?count1.intValue():0);

        List<CourseStudentRel> list = courseStudentRelService.lambdaQuery()
                .eq(CourseStudentRel::getDelFlag,"0")
                .in(CourseStudentRel::getIsChangeClass,new String[]{"0","2"})
                .list();
        List<CourseStudentRel> list1 = courseStudentRelService.lambdaQuery()
                .eq(CourseStudentRel::getDelFlag,"0")
                .ge(BaseEntity::getCreateTime,startTime)
                .le(BaseEntity::getCreateTime,endTime)
                .in(CourseStudentRel::getIsChangeClass,new String[]{"0","2"})
                .list();
        BigDecimal reduce1 = list1.stream().map(CourseStudentRel::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setTodayMoney(reduce1);
        if (!CollectionUtils.isEmpty(list)){
            BigDecimal reduce = list.stream().map(CourseStudentRel::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setTotalMoney(reduce);
            int totalNum = 0;
            int resTotalNum = 0;
            for (CourseStudentRel courseStudentRel : list) {
                totalNum = totalNum + courseStudentRel.getNum();
                resTotalNum = resTotalNum + courseStudentRel.getResNum();
            }
            vo.setResHour(resTotalNum);
            vo.setTotalHour(totalNum);
        }
        Map<LocalDate, List<CourseStudentRel>> collect = list.stream().collect(Collectors.groupingBy(b ->
                LocalDateTime.ofInstant(b.getCreateTime().toInstant(), ZoneId.systemDefault()).toLocalDate()));
        List<Map<LocalDate,Object>> list2 = new ArrayList<>();
        if (!CollectionUtils.isEmpty(collect)){
            for (Map.Entry<LocalDate, List<CourseStudentRel>> dateListEntry : collect.entrySet()) {
                List<CourseStudentRel> value = dateListEntry.getValue();
                BigDecimal reduce = value.stream().map(CourseStudentRel::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                Map<LocalDate, Object> hashMap = new HashMap<>();
                hashMap.put(dateListEntry.getKey(),reduce);
                list2.add(hashMap);
            }
        }
        //每日收入趋势图 按年月日来分组
        vo.setIncomeDetails(list2);
        Map<Long, List<CourseStudentRel>> collect1 = list.stream().collect(Collectors.groupingBy(CourseStudentRel::getTeacherId));
        List<Map<String,Object>> list3 = new ArrayList<>();
        if (!CollectionUtils.isEmpty(collect1)){
            for (Map.Entry<Long, List<CourseStudentRel>> longListEntry : collect1.entrySet()) {
                int size = longListEntry.getValue().size();
                Map<String, Object> hashMap = new HashMap<>();
                SysTeacher sysTeacher = sysTeacherMapper.selectSysTeacherById(longListEntry.getKey());
                if (sysTeacher != null){
                    hashMap.put(sysTeacher.getName(),size);
                }
                list3.add(hashMap);
            }
            vo.setTeacherRanking(list3);
        }
        return vo;
    }
}
